﻿using System.Collections;
using System.Web;
using DoNet.Helper;

namespace DoNet.Platform.JD
{
    /// <summary>
    /// 京东Access Token
    /// </summary>
    public class TokenApi
    {
        /// <summary>
        /// 获取Access Token
        /// </summary>
        /// <param name="app_key">应用标识</param>
        /// <param name="app_secret">应用密钥</param>
        /// <param name="code">用户授权后得到code </param>
        /// <returns></returns>
        public static ReturnData GetToken(string app_key, string app_secret, string code)
        {
            /*
            2.通过code获取access_token

            https://open-oauth.jd.com/oauth2/access_token?app_key=XXXXX&app_secret=XXXXX&grant_type=authorization_code&code=XXXXX

            参数说明：

            参数	是否必须	说明
            app_key 是 应用标识
            app_secret 是 应用密钥
            grant_type 是 固定为authorization_code
            code 是 为步骤1中获取的code

            返回说明：
            {
               "access_token": "b6787895ee524cf0b07c81f2566aafa1gm4o",
               "expires_in": 31536000,
               "refresh_token": "097r1b3d3f4e4c55a4e45d08d29aafe0otfi",
               "scope": "snsapi_base",
               "open_id": "KV-4zX_bLFUD6617rH7y0ipkr5n2-3uU6WCAnL4999U",
               "uid": "5618242670",
               "time": 1695200156425,
               "token_type": "bearer",
               "code": 0,
               "xid": "o*AAQu5M9OMBphkmnhfTKWVl_IZTBkNsDX107fohhH6_DTli9rrUY"
            }

            返回参数说明：

            参数	        说明
            access_token    接口调用令牌
            expires_in      令牌有效时间, 单位秒
            refresh_token   用户刷新access_token
            scope           用户授权的作用域，使用逗号（,）分隔
            open_id         授权用户唯一标识（旧）
            time	        授权时间 
            xid	            授权用户唯一标识（新）尽量使用xid作为用户标识信息


            错误返回样例：

            {"code":40029,"msg":"invalid code",”uid”:”xxxxxx”}
            */

            string reqUrl = CommonConfig.WebApiUrl_JD_oauth + string.Format("/oauth2/access_token?grant_type=authorization_code&app_key={0}&app_secret={1}&code={2}", app_key, app_secret, code);
            var result = HttpHelper.HttpGet(reqUrl);
            if (result.success)
            {
                var obj = JsonHelper.DeserializeObject<dynamic>(result.data);
                if (obj != null)
                {
                    /*
                    {
                        "msg":"缺少参数 app_secret",
                        "code":"100004"
                    }
                    */
                    if (obj.code != null)
                    {
                        return new ReturnData()
                        {
                            success = false,
                            message = obj.msg,
                            data = result.data
                        };
                    }
                    else
                    {
                        return result;
                    }
                }
                else
                {
                    return result;
                }
            }
            else
            {
                return result;
            }
        }

        /// <summary>
        /// 获取授权URL
        /// </summary>
        /// <param name="app_key">应用标识</param>
        /// <param name="redirect_uri">回调地址,必须与开发者控制里的URL保持一致</param>
        /// <param name="scope">应用的作用域 snsapi_base（静默模式，登录+授权一步完成） snsapi_union_login（拉端模式，拉起京东APP端完成授权） snsapi_app_union_login（非拉端模式，当前APP直接打开H5授权页完成授权） scope=snsapi_jdjr_union_login （（拉端模式，拉起京东金融APP端完成授权））</param>
        /// <param name="state">维持应用的状态，传入值与返回值保持一致。</param>
        /// <returns></returns>
        public static string GetAuthorizeUrl(string app_key, string redirect_uri, string scope, string state = "")
        {
            /*
            1.请求code
            https://open-oauth.jd.com/oauth2/to_login?app_key=XXXXX&response_type=code&redirect_uri=XXXXX&state=20180416&scope=snsapi_base

            参数说明：

            参数	是否必须	说明
            app_key 是 应用标识
            response_type 是 固定为code
            redirect_uri 是 回调地址,必须与开发者控制里的URL保持一致
            scope 是 应用的作用域 snsapi_base（静默模式，登录+授权一步完成） snsapi_union_login（拉端模式，拉起京东APP端完成授权） snsapi_app_union_login（非拉端模式，当前APP直接打开H5授权页完成授权） scope=snsapi_jdjr_union_login （（拉端模式，拉起京东金融APP端完成授权））
            state 否 用于保持请求和回调的状态，授权请求后原样带回给第三方。该参数可用于防止csrf攻击（跨站请求伪造攻击），建议第三方带上该参数，可设置为简单的随机数加session进行校验 

            返回说明：
            用户允许授权后,会跳转到指定的redirect_uri并多添加两个参数code和state参数
            redirect_uri?code=CODE&state=STATE
            若用户禁止授权,则会重定向后不会带上code参数, 仅会带上state参数
            redirect_uri?state=STATE
            */
            string param = string.Format("/oauth2/to_login?response_type=code&app_key={0}&redirect_uri={1}&scope={2}", app_key, HttpUtility.UrlEncode(redirect_uri), scope);
            if(!string.IsNullOrWhiteSpace(state))
            {
                param += string.Format("&state={0}", state);
            }
            return CommonConfig.WebApiUrl_JD_oauth + param;
        }

        /// <summary>
        /// jingdong.user.getUserInfoByOpenId（根据openId获取用户信息）
        /// 根据openId获取用户昵称等信息，openid可通过授权获取
        /// </summary>
        /// <param name="access_token">采用OAuth授权方式为必填参数</param>
        /// <param name="appKey">填写应用的appkey，可以在控制台-->应用管理中查看appkey</param>
        /// <param name="appSecret">填写应用的秘钥，可以在控制台-->应用管理中查看秘钥</param>
        /// <param name="xId">用户标识（openId）</param>
        /// <returns></returns>
        public static ReturnData GetUserInfo(string access_token, string appKey, string appSecret, string xId)
        {
            string method = "jingdong.user.getUserInfoByXId";
            string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            string version = "2.0";

            Hashtable parameters = new Hashtable();
            parameters.Add("method", method);
            parameters.Add("access_token", access_token);
            parameters.Add("app_key", appKey);
            parameters.Add("timestamp", timestamp);
            parameters.Add("format", "json");
            parameters.Add("v", version);
            parameters.Add("XId", xId);

            string sign = JDCommon.GenerateSign(appKey, access_token, appSecret, method, timestamp, version, JsonHelper.SerializeObject(parameters));
            parameters.Add("sign", sign);

            string param = JsonHelper.SerializeObject(parameters);
            string reqUrl = CommonConfig.WebApiUrl_JD_opendj + "/api";
            var result = HttpHelper.HttpPost(reqUrl, param);
            if (result.success)
            {
                var obj = JsonHelper.DeserializeObject<dynamic>(result.data);
                if (obj != null)
                {
                    /*
                    {
                        "jingdong_user_getUserInfoByOpenId_responce": {
                            "getuserinfobyappidandopenid_result": {
                                "msg": "成功",
                                "code": "0",
                                "data": {
                                    "gendar": "0",
                                    "nickName": "zhangsan",
                                    "imageUrl": "//passport.jd.com/new/misc/skin/df/i/no-img_mid_.jpg"
                                }
                            }
                        }
                    }

                    {
                        "code": "0",
                        "errorMessage": "成功",
                        "errorSolution": "成功"
                    }
                    */
                    if (obj.errorMessage != null)
                    {
                        return new ReturnData()
                        {
                            success = false,
                            message = obj.errorMessage,
                            data = result.data
                        };
                    }
                    else
                    {
                        var responce = obj.jingdong_user_getUserInfoByOpenId_responce;
                        if (responce != null)
                        {
                            var res = responce.getuserinfobyappidandopenid_result;
                            if (res != null)
                            {
                                if (res.code == "0")
                                {
                                    return new ReturnData()
                                    {
                                        success = true,
                                        message = res.msg,
                                        data = result.data
                                    };
                                }
                                else
                                {
                                    return new ReturnData()
                                    {
                                        success = false,
                                        message = res.msg,
                                        data = result.data
                                    };
                                }
                            }
                            else
                            {
                                return new ReturnData()
                                {
                                    success = false,
                                    message = "接口返回数据data的jingdong_user_getUserInfoByOpenId_responce的getuserinfobyappidandopenid_result为null"
                                };
                            }
                        }
                        else
                        {
                            return new ReturnData()
                            {
                                success = false,
                                message = "接口返回数据data的jingdong_user_getUserInfoByOpenId_responce为null"
                            };
                        }
                    }
                }
                else
                {
                    return new ReturnData()
                    {
                        success = false,
                        message = "接口返回数据data为null"
                    };
                }
            }
            else
            {
                return result;
            }
        }
    }
}
